package com.demo.util.excel.utils;

import com.demo.util.CollUtil;
import com.demo.util.equals.beans.EqualsRangeVO;
import com.demo.util.equals.functional.Equals;
import com.demo.util.equals.utils.EqualsUtil;
import com.demo.util.excel.beans.ExcelColumnVO;
import com.demo.util.excel.beans.ExcelHeaderVO;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;
import java.util.stream.Collectors;

public class ExcelMergeUtil {

    /**
     * 合并表头单元格
     */
    public static <T> void mergeHeaderCell(Sheet sheet, ExcelHeaderVO<T> headerInfo) {
        int headerStartIndex = headerInfo.getStartIndex();
        int maxLength = headerInfo.getMaxLength();
        List<List<ExcelColumnVO<T>>> headerColumns = headerInfo.getHeaderColumns();
        // 处理向下合并
        for (int colIndex = 0; colIndex < headerColumns.size(); colIndex++) {
            List<ExcelColumnVO<T>> rowsInCol = headerColumns.get(colIndex);
            int sizeInCol = rowsInCol.size();
            if (sizeInCol == maxLength) {
                continue;
            }
            int rowSize = maxLength - sizeInCol;
            int lastIndex = sizeInCol - 1;
            mergeCell(sheet, lastIndex, colIndex, rowSize, 0, headerStartIndex, 0);
        }
        // 处理向右合并
        for (int rowIndex = 0; rowIndex < maxLength; rowIndex++) {
            final int finalRowIndex = rowIndex;
            List<ExcelColumnVO<T>> colsInRow = headerColumns
                    .stream()
                    .map(rowsInCol -> CollUtil.getOrNull(rowsInCol, finalRowIndex))
                    .collect(Collectors.toList());
            List<EqualsRangeVO> equalsRange = EqualsUtil.getEqualsRange(colsInRow, (a, b) -> a == b);
            for (EqualsRangeVO range : equalsRange) {
                mergeCell(sheet, rowIndex, range.getIndex(), 0, range.getSize(), headerStartIndex, 0);
            }
        }
    }

    /**
     * 合并数据单元格
     */
    public static <T> void mergeDataCell(
            Sheet sheet,
            List<ExcelColumnVO<T>> columns,
            List<T> data,
            int dataStartIndex
    ) {
        for (int colIndex = 0; colIndex < columns.size(); colIndex++) {
            ExcelColumnVO<T> column = columns.get(colIndex);
            Equals<T> merge = column.getMerge();
            if (merge == null) {
                continue;
            }
            List<EqualsRangeVO> equalsRange = EqualsUtil.getEqualsRange(data, merge);
            for (EqualsRangeVO range : equalsRange) {
                mergeCell(sheet, range.getIndex(), colIndex, range.getSize(), 0, dataStartIndex, 0);
            }
        }
    }

    private static void mergeCell(Sheet sheet, int rowIndex, int colIndex, int rowSize, int colSize, int rowOffset, int colOffset) {
        sheet.addMergedRegion(new CellRangeAddress(
                rowOffset + rowIndex,
                rowOffset + rowIndex + rowSize,
                colOffset + colIndex,
                colOffset + colIndex + colSize
        ));
    }

}
